package com.cheng.algorithm.sort;

import java.util.Arrays;

/**
 * @User Administrator
 * @Classname MergeSort
 * @Project Data-structure-and-algorithm
 * @Description 归并排序
 * 介绍：
 * 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法，
 * 该算法采用经典的分治（divide-and-conquer）策略〈分治法将问题分(divide)成一些小的问题然后递归求解，
 * 而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起，即分而治之)。
 *
 * @Author wpcheng
 * @Create 2021-08-08-10:08
 * @Version 1.0
 */
public class MergeSort {
    public static void main(String[] args) {
        int[] arr = {8, 4, 5, 7, 1, 3, 6, 2};
        int temp[] = new int[arr.length];
        mergeSort(arr,0, arr.length-1, temp);
        System.out.println(Arrays.toString(arr));

    }

    public static void mergeSort(int[] arr,int left,int right,int[] temp){
        if (left < right){
            int mid = (left + right) / 2;
            //向左递归
            mergeSort(arr,left,mid,temp);
            //向右递归
            mergeSort(arr,mid + 1,right,temp);
            //合并
            merge(arr,left,mid,right,temp);
        }
    }



    /**
     * 合并的方法：
     * @param arr  待排序的数组
     * @param left  左边有序数组的初始索引
     * @param mid   位于左右两个数组中间的索引
     * @param right   右边有序数组的最后索引
     * @param temp  用于存放临时结果的数组
     */
    public static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left; //用于遍历左边有序数组的索引
        int j = mid + 1;  //用于遍历右边有序数组的索引
        int t = 0; //temp的初始索引

        while (i <= mid && j <= right){
            //如果左边有序序列当前元素小于等于右边有序序列当前元素
            if (arr[i] <= arr[j]){
                temp[t] = arr[i]; //就把左边小的元素放入临时数组
                i++;
                t++;
            }else { //反之，就把右边小的元素放入临时数组
                temp[t] = arr[j];
                j++;
                t++;
            }
        }
        //把左边有剩余的元素依次填入临时数组
        while (i <= mid){
            temp[t] = arr[i];
            i++;
            t++;
        }
        //把右边有剩余的元素依次填入临时数组
        while (j <= right){
            temp[t] = arr[j];
            j++;
            t++;
        }
        //将temp数组的元素放入arr
        t = 0;
        int tempLeft = left;
        while (tempLeft <= right){
            arr[tempLeft] = temp[t];
            t++;
            tempLeft++;
        }
    }
}
